
var gomoku_logic = {
    panel:{
        // x:15,
        // y:15
    },
    status_const:{
        me:1,
        rival:2
    },
    is_own_turn:true, //是否该己方下子，
    all_matrix:[],//棋盘所有子的矩阵
    all_win_arr:[], //存储所有赢法数组 ['x-y','x1-y1'] //x,y索引做成字符串
    total_win_count:0,//所有赢法总数
    my_win_arr:[],//我自己所有能赢的数组
    rival_win_arr: [],//对手所有能赢的数组
    is_game_over:false,//是否游戏结束
    own_weight:[],//自己的权重，计算 ai 时用到
    rival_weight:[],//对手权重 ，计算 ai 时用到
    renderView:(x,y,is_rival) => {},//放下子的UI逻辑，由外部传入
    mySucceed:(completed_arr) => {},//我成功的逻辑，由外部传入
    myFailed:(completed_arr) => {},//我失败的逻辑，由外部传入
    calcBefore:() => {},
    calcAfter:() => {},
    init(params,is_ai_first) {
        this.is_game_over = false
        this.is_own_turn = true
        this.total_win_count = 0
        this.all_win_arr = []

        Object.assign(this,params)
        this.all_matrix = this.setDefaultValue( 0);
        this.initWinArr();
        if(is_ai_first)
        {
            console.log('isaifirst');
            this.putSinglePawn(parseInt(this.panel.x/2),parseInt(this.panel.y/2),true) //如果让 ai 先走,则先占中间
        }
        return this;
    },
    setDefaultValue(val) {
        var obj = []
        for(var i=0; i<this.panel.x; i++){
            obj[i] = [];
            for(var j=0; j<this.panel.y; j++){
                obj[i][j] = val;
            }
        }
        return obj;
    },
//    设置所有赢法，并把赢法的所有 xy 以 x-y的格式加入单个数组 type 可取值 -|\/
    initWinArr() {
        ['-','|','\\','/'].forEach((type) => {
            var x_max = this.panel.x;
            var y_max = this.panel.y - 4;
            if (['\\', '/'].includes(type)) {
                x_max = this.panel.x - 4;//    如果是斜线，则 x 要减小 4
            }
            for(var i = 0; i < x_max; i++){
                for(var j= 0; j < y_max; j++){
                    this.all_win_arr[this.total_win_count] = []
                    for(var k = 0; k < 5; k++){
                        var  default_xy_str = "" + i + '-' +(j + k);//默认是 - 线
                        if (type === '|') {
                            default_xy_str = "" + (j + k) + '-' + i;
                        }else if (type === '\\') {
                            default_xy_str = "" + (i + k) + '-' + (j + k);
                        } else if(type === '/') {
                            default_xy_str = "" + (i+k) + '-' + (this.panel.y -1-j-k);
                        }
                        this.all_win_arr[this.total_win_count].push(default_xy_str)
                    }
                    this.total_win_count++;
                }
            }
        })
        //    再把自己和对手的所有赢法初始化
        for (var i in this.all_win_arr) {
            this.my_win_arr[i] = 0;
            this.rival_win_arr[i] = 0;
        }
    },
    putSinglePawn(x,y,is_rival){
        this.renderView(x,y,is_rival)//渲染
        this.all_matrix[x][y] = is_rival ? this.status_const.rival : this.status_const.me;
    },
    onClickEvent(x,y) {
        if (this.is_game_over) {
            console.log('gameover')
            return false;//
        }
        if (!this.is_own_turn) {
            console.log('not my turn')
            return false;
        }
        if (this.all_matrix[x][y]) {
            console.log("exists")
            return false; //此点有值 ，则忽略
        }
        this.putSinglePawn(x, y, false)
        var start = Date.now();

        for (var i in this.all_win_arr) {
            var pawn_count = this.calcWinWeight(this.all_win_arr[i],x,y,this.status_const.rival,this.status_const.me)
            if (pawn_count) {
                // if (this.all_win_arr[i].includes(x + '-' + y)) {
                this.my_win_arr[i] = pawn_count;//如果有此位置，由我的这一条的赢面大一些
                if (this.my_win_arr[i] === 5) {
                    this.is_game_over = true;
                    this.mySucceed(this.all_win_arr[i]);//成功
                }
            }
        }
        console.log(Date.now() - start);

        if (!this.is_game_over) {
            //还没结束 ，则计算对手（目前是 ＡＩ 的下棋）
            this.is_own_turn = !this.is_own_turn;
            this.calcAi();
        }
        console.log(Date.now() - start);
    },
    calcAi() {
        if (this.calcBefore) {
            this.calcBefore()
        }
        var current_max_weight = -1;//当前最大权重
        var dest_point = {x:-1,y:-1}// 比如 {x,y}
        // var dest_point = {x:0,y:0}// 比如 {x,y}
        // ai各个逻辑的权重
        var my_weights = {
            1: 1000,
            2: 2000,
            3: 8000,
            4: 40000,
        }
        var rival_weights = {
            1:1100,
            2:2200,
            3:8800,
            4:44000,
        }
        var start = Date.now();
        this.own_weight = this.setDefaultValue( 0);
        this.rival_weight = this.setDefaultValue( 0);
        console.log(Date.now() - start);
        for (var x in this.all_matrix) {
            for (var y in this.all_matrix[x]) {
                //如果此点有值，则跳过
                if (this.all_matrix[x][y]) {
                    continue;
                }
                //    遍历算出当前所有赢法
                for (var i in this.all_win_arr) {
                    this.my_win_arr[i] = this.calcWinWeight(this.all_win_arr[i],x,y,this.status_const.rival,this.status_const.me)
                    this.rival_win_arr[i] = this.calcWinWeight(this.all_win_arr[i],x,y,this.status_const.me,this.status_const.rival)
                    for (var m_w in my_weights) {//先计算下我方的权重
                        if(this.my_win_arr[i] === parseInt(m_w)){
                            this.own_weight[x][y] += my_weights[m_w];
                            break;
                        }
                    }
                    for (var r_w in rival_weights) {//再算下对方的权重
                        if(this.rival_win_arr[i] === parseInt(r_w)){
                            this.rival_weight[x][y] += rival_weights[r_w];
                            break;
                        }
                    }
                    //再算下 自己的权重大时
                    if (this.own_weight[x][y] > current_max_weight
                        || ( this.own_weight[x][y] === current_max_weight
                            && this.rival_weight[x][y] > this.rival_weight[dest_point.x][dest_point.y]
                        )
                    ) {
                        current_max_weight = this.own_weight[x][y];
                        dest_point = {x,y};
                    }
                    //    再计算下对手的权重大时
                    if (this.rival_weight[x][y] > current_max_weight
                        || ( this.rival_weight[x][y] === current_max_weight
                            && this.own_weight[x][y] > this.own_weight[dest_point.x][dest_point.y]
                        )
                    ) {
                        current_max_weight = this.rival_weight[x][y]
                        dest_point = {x,y}
                    }
                }
            }
        }

        //    按下子
        this.putSinglePawn(dest_point.x, dest_point.y, true)
        for (var c = 0; c < this.total_win_count; c++) {
            this.rival_win_arr[c] = this.calcWinWeight(this.all_win_arr[c],dest_point.x,dest_point.y,this.status_const.me,this.status_const.rival)
            if (1 ) {
                if (this.rival_win_arr[c] === 5) {
                    this.is_game_over = true;
                    this.myFailed(this.all_win_arr[c]);//成功
                }
            }
        }
        if (this.calcAfter) {
            this.calcAfter()
        }
        if (!this.is_game_over) {
            this.is_own_turn = !this.is_own_turn;
        }
        return ""
    },
    calcWinWeight(str_arr,x,y,rival_status,own_status) {
        var dest_count = 0;
        if(str_arr.includes(x+'-'+y)){ //有存在则再说
            for (var i in str_arr) {
                var temp_x,temp_y;
                [temp_x, temp_y] = str_arr[i].split('-');
                if (this.all_matrix[temp_x][temp_y] === rival_status) {
                    dest_count = 0;
                    break;//如果该赢法有对手的子，则返回0
                }
                if (this.all_matrix[temp_x][temp_y] === own_status) {
                    dest_count++;
                }
            }
            return dest_count;
        }
        return 0;
    },
}

export default gomoku_logic;
